#include "TopWidget.h"
#include "ui_TopWidget.h"

TopWidget::TopWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::TopWidget)
{
    ui->setupUi(this);

    ui->btnCamerMoveMode->setVisible(false);

    connect(ui->btnGetDepthBufTest1,SIGNAL(clicked()),
            ui->openGLWidget,SLOT(on_btnGetDepthBufTest1Clicked())
            );


    connect(ui->btnVolumeTest,SIGNAL(clicked()),
            ui->openGLWidget,SLOT(on_btnVolumeTestClicked())
            );

    connect(ui->btnScaleMode,SIGNAL(toggled(bool)),
            ui->openGLWidget,SLOT(setCameraScaleMode(bool))
            );

    connect(ui->btnTestSurfaceVis,SIGNAL(toggled(bool)),
            ui->openGLWidget,SLOT(testSurfaceVisible(bool))
            );

    setPseudoColor(true);
}

TopWidget::~TopWidget()
{
    delete ui;
}

void TopWidget::on_btnResetCamera_clicked()
{
    ui->openGLWidget->resetCamera();
    ui->openGLWidget->update();
}

void TopWidget::on_btnOrthoMode_toggled(bool checked)
{
    ui->openGLWidget->setCameraOrtho(checked);
    ui->openGLWidget->update();
}

void TopWidget::on_btnCamerMoveMode_toggled(bool checked)
{
    ui->openGLWidget->setCameraMoveMode(checked);
    ui->openGLWidget->update();
}

void TopWidget::on_sliderOpacity_valueChanged(int value)
{
    double opacity = ui->sliderOpacity->maximum() - ui->sliderOpacity->minimum();
    opacity = value / opacity;
    opacity = opacity * 0.04995 + 0.00005;
//    qDebug() << opacity;
    ui->openGLWidget->setVolumeOpacity(opacity);
    ui->openGLWidget->update();
}

void TopWidget::on_sliderBrightness_valueChanged(int value)
{
    double brightness = ui->sliderBrightness->maximum() - ui->sliderBrightness->minimum();
    brightness = value / brightness;
    brightness = brightness * 9.99 + 0.01;
//    qDebug() << brightness;
    ui->openGLWidget->setVolumeBrightness(brightness);
    ui->openGLWidget->update();
}


void TopWidget::on_sliderThreshold_valueChanged(int value)
{
    double thres = ui->sliderThreshold->maximum() - ui->sliderThreshold->minimum();
    thres = value / thres;
    ui->openGLWidget->setVolumeThreshold(thres);
    ui->openGLWidget->update();
}

void TopWidget::on_sliderGradient_valueChanged(int value)
{
    double grad = ui->sliderGradient->maximum() - ui->sliderGradient->minimum();
    grad = 10.0 * value / grad;
    ui->openGLWidget->setVolumeGradient(grad);
    ui->openGLWidget->update();
}


void TopWidget::on_btnPseudoColor_toggled(bool checked)
{
    setPseudoColor(checked);
    ui->openGLWidget->update();
}

void TopWidget::setPseudoColor(bool pseudo)
{
//    colorFunc->AddRGBSegment(0,0,0,0,
//                             103,103/255.0,0,0
//                             );
//    colorFunc->AddRGBSegment(104,104/255.0,0,0,
//                             142,142/255.0,64/255.0,0
//                             );
//    colorFunc->AddRGBSegment(143,143/255.0,65/255.0,2/255.0,
//                             239,239/255.0,227/255.0,218/255.0
//                             );
//    colorFunc->AddRGBSegment(240,240/255.0,229/255.0,221/255.0,
//                             255,1,1,1
//                             );
    if(pseudo){
        ui->openGLWidget->clearVoxelRGBSegmentPoints();
        ui->openGLWidget->addVoxelRGBSegment(0,0,0,0,
                                             103,103/255.0,0,0
                                             );
        ui->openGLWidget->addVoxelRGBSegment(104,104/255.0,0,0,
                                             142,142/255.0,64/255.0,0
                                             );
        ui->openGLWidget->addVoxelRGBSegment(143,143/255.0,65/255.0,2/255.0,
                                             239,239/255.0,227/255.0,218/255.0
                                             );
        ui->openGLWidget->addVoxelRGBSegment(240,240/255.0,229/255.0,221/255.0,
                                             255,1,1,1
                                             );
        ui->openGLWidget->modifiedVoxelColorFunc();
    }else{
        ui->openGLWidget->resetVoxelRGBSegmentPoints();
        ui->openGLWidget->modifiedVoxelColorFunc();
    }
}

void TopWidget::on_btnLookatXY_clicked()
{
    ui->openGLWidget->resetCameraToXYPlane();
    ui->openGLWidget->update();
}

void TopWidget::on_btnLookatXZ_clicked()
{
    ui->openGLWidget->resetCameraToXZPlane();
    ui->openGLWidget->update();
}

void TopWidget::on_btnLookatYZ_clicked()
{
    ui->openGLWidget->resetCameraToYZPlane();
    ui->openGLWidget->update();
}

bool TopWidget::readAVI8UC1Data(QString &fileName, unsigned char **dataptr,
                                int &width, int &height, int &count)
{
    cv::VideoCapture capture;
    cv::Mat frameimg;
    capture.open(fileName.toLocal8Bit().toStdString());

    width=static_cast<int>(capture.get(CV_CAP_PROP_FRAME_WIDTH));
    height=static_cast<int>(capture.get(CV_CAP_PROP_FRAME_HEIGHT));
    count=static_cast<int>(capture.get(CV_CAP_PROP_FRAME_COUNT));

    if(!capture.isOpened()
            || (width * height * count < 1)
            ){
        capture.release();
        return false;
    }

    unsigned char *cuboidData=
            new unsigned char[static_cast<quint64>(width*height*count)];
    if(!cuboidData){
        capture.release();
        return false;
    }

    cv::Mat ttmat,graymat;
    bool hasframe = false;
    size_t framesize=static_cast<size_t>(width*height);
    for (int i = 0; i < count; ++i) {
        try {
            hasframe=capture.read(ttmat);
            if(!hasframe){
                count=i;
                break;
            }
            if(!ttmat.empty()){
                cv::cvtColor(ttmat,graymat,CV_BGR2GRAY);
                memcpy(cuboidData+static_cast<quint64>(i)*framesize,graymat.data,framesize);
            }
        } catch (char *) {
            delete [] cuboidData;
            capture.release();
            return false;
        }
    }

    if(!capture.isOpened()
            || (width * height * count < 1)
            ){
        capture.release();
        return false;
    }

//    while (capture.read(frameimg)) {
//     cv::imshow("avi",frameimg);
//     cv::waitKey(0);
//     qDebug()<<"?";
//    }
//    cv::destroyAllWindows();
//    qDebug()<<"2";

    capture.release();
    *dataptr = cuboidData;
    qDebug()<<"AVI data width x height x count = "<< width << height << count;
    return true;
}

void TopWidget::on_btnLoadAVI_clicked()
{
    QString fileName = QFileDialog::getOpenFileName(this,
                                                    tr("Load AVI File"), QString(), tr("AVI Files (*.avi)"));

    if(fileName.isNull() || fileName.isEmpty()) return;

    int width = 0,height = 0,count = 0;
    unsigned char *dataptr = nullptr;

    if(readAVI8UC1Data(fileName,&dataptr,
                    width,height,count
                       )){

        float thres = ui->sliderThreshold->maximum() - ui->sliderThreshold->minimum();      //从中间帧图像估算体绘制最小累计阈值
        double minvalue,maxvalue;
        cv::Point minloc,maxloc;
        cv::Mat hist;
        cv::Mat middleframe(height,width,CV_8UC1,dataptr + height * width * (count / 2));
        int channel[] = {0};     // 二维的写法为 {0,1} 通道0范围作为宽度 通道1范围作为高度 生成二维图像结果
        int histSize[] = {256};  // 二维的写法为 {60,64} 会生成60x64的二维图像结果
        const float range0[] = {0,255}; // 二维的写法为 range0[] = {0,255} range1[] = {0,255}
        const float *ranges[] = {range0};  // 二维的写法为ranges[] = {range0,range1};
        // 计算直方图
        cv::calcHist(&middleframe,1,channel,cv::Mat(),hist,1,histSize,ranges);
        hist.at<float>(0) = 0;   // 0值像素不统计
        cv::minMaxLoc(hist,&minvalue,&maxvalue,&minloc,&maxloc);
//        qDebug()<< (hist.type() == CV_32F);
//        for (int i = 0; i < 256; ++i) {
//            // at<T>(row,col), hist.at<float>(i,0) 行对应第一维
//            qDebug()<<i<<": "<<hist.at<float>(i);
//        }

        ui->openGLWidget->setVolume8UC1Data(dataptr,width,height,count);
        ui->openGLWidget->resetCameraToXYPlane();
//        ui->openGLWidget->update();
        thres = thres * 1.1f * maxloc.y / 255.0f;      // 最多数量的像素值 105%为阈值
        ui->sliderThreshold->setValue(static_cast<int>(thres));

        thres = ui->sliderOpacity->maximum() - ui->sliderOpacity->minimum();
        thres = 8.0f * thres / (height * 0.1f + 1.0f);   //  默认最多穿透5%的像素
        ui->sliderOpacity->setValue(static_cast<int>(thres));

        thres = ui->sliderBrightness->maximum() - ui->sliderBrightness->minimum();
        thres = 0.15f * thres * 0.5f * 255.0f / (4.0f * maxloc.y) ; //  阈值的40倍作为半亮度
        ui->sliderBrightness->setValue(static_cast<int>(thres));

        ui->openGLWidget->update();

        if(dataptr){
            delete [] dataptr;
            dataptr = nullptr;
        }
    }else{
        QMessageBox msgBox;
        msgBox.setText("Load AVI file Failed!");
        msgBox.exec();

    }


}
